package com.bwie.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bwie.mapper.ActiveRuleMapper;
import com.bwie.mapper.WinRecordMapper;
import com.bwie.pojo.ActiveRule;
import com.bwie.pojo.WinRecord;
import com.bwie.service.IuserService;
import com.bwie.utils.R;
import com.bwie.vo.PageInfoVo;
import io.jsonwebtoken.Jwts;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bwie.pojo.Active;
import com.bwie.mapper.ActiveMapper;
import com.bwie.service.ActiveService;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;

@Service
public class ActiveServiceImpl extends ServiceImpl<ActiveMapper, Active> implements ActiveService{
    @Autowired
    ActiveMapper activeMapper;

    @Autowired
    ActiveRuleMapper activeRuleMapper;

    @Autowired
    HttpServletRequest request;

    @Autowired
    StringRedisTemplate redisTemplate;

    @Autowired
    WinRecordMapper winRecordMapper;

    @Autowired
    IuserService iuserService;

    @Autowired
    RedissonClient redissonClient;

    @Override
    public R activeList(PageInfoVo pageInfoVo) {
        Page<Active> page = new Page<>(pageInfoVo.getPageNum(), pageInfoVo.getPageSize());
        Page<Active> activePage=activeMapper.getActiveList(page,pageInfoVo);
        return R.ok().setData(activePage);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public R addActive(Active active) {
        String token = request.getHeader("token");
        if(token==null){
            return R.error().setMsg("请先登录");
        }
        Integer userId = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody().get("userId", Integer.class);
        String userName = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody().get("userName", String.class);

        try {
            //处理开始时间结束时间
            List<String> activeTime = active.getActiveTime();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            active.setBeginTime(format.parse(activeTime.get(0)));
            active.setEndTime(format.parse(activeTime.get(1)));
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }

        //审计字段
        active.setCreateBy(userName);
        active.setCreateTime(new Date());
        //1添加抽奖活动
        activeMapper.insert(active);

        //2添加抽奖活动规则
        for (ActiveRule activeRule : active.getRuleList()) {
            activeRule.setActiveId(active.getActiveId());
            activeRuleMapper.insert(activeRule);
            activeRule.setCreateBy(userName);
            activeRule.setCreateTime(new Date());
        }
        return R.ok();
    }

    @Override
    public R joinActive(Integer activeId) {

        String token = request.getHeader("token");
        if(token==null){
            return R.error().setMsg("请先登录");
        }
        Integer userId = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody().get("userId", Integer.class);
        String userName = Jwts.parser().setSigningKey("bwie").parseClaimsJws(token).getBody().get("userName", String.class);

        Active active = activeMapper.selectById(activeId);
        if(active==null){
            return R.error().setMsg("活动不存在");
        }



        //检查活动状态
        if(active.getActiveStatus()!=1){
            return R.error().setMsg("活动已结束，谢谢参与");
        }

        //活动是否开始
        long currentTimeMillis = System.currentTimeMillis();
        if(currentTimeMillis<active.getBeginTime().getTime()){
            return R.error().setMsg("活动未开始，请耐心等待");
        }
        if(currentTimeMillis>active.getEndTime().getTime()){
            return R.error().setMsg("活动已结束，谢谢参与");
        }



        //检查用户是否有资格抽奖
        String joinKey="join:"+activeId+"-"+userId;
        Boolean hasKey1 = redisTemplate.hasKey(joinKey);
        if(!hasKey1){
            //说明从来没有参与过
            redisTemplate.opsForValue().set(joinKey,""+active.getFreeTimes());
        }else {
            //用户参与过
        }

            Long times = redisTemplate.opsForValue().decrement(joinKey);
            if (times < 0) {
                return R.error().setMsg("您已经没有抽奖次数，请勿重复参与");
            }



            String key = "active-" + activeId;
            Boolean hasKey = redisTemplate.hasKey(key);
            if (!hasKey) {
                //活动数据没有加载，加载活动数据
                List<ActiveRule> activeRules = activeRuleMapper.selectList(
                        new QueryWrapper<ActiveRule>().lambda().eq(ActiveRule::getActiveId, activeId)
                );

                //把活动规则放入缓存
                ArrayList<String> list = new ArrayList<>();
                for (ActiveRule activeRule : activeRules) {

                    list.add("" + activeRule.getRuleId());
                }

                //填充100个规则，如果ID为0表示没有中奖
                while (list.size() < 100) {
                    list.add("0");
                }

                //打乱列表顺序
                Collections.shuffle(list);

                //把打乱后的数据，放入redis的list中
                redisTemplate.opsForList().leftPushAll(key, list);
            }



        //抽奖
        String s = redisTemplate.opsForList().rightPop(key);
        if(s==null){
            active.setActiveStatus(1);
            active.setUpdateBy(userName);
            active.setUpdateTime(new Date());
            activeMapper.updateById(active);
            return R.error().setMsg("谢谢参与");
        }
        WinRecord winRecord = new WinRecord();
        if(s.equals("0")){
            winRecord.setUserId(userId);
            winRecord.setRuleId(0);
            winRecord.setRecordDesc("未中奖");
            winRecord.setActiveType(winRecord.getActiveType());
            winRecord.setWinFlag(0);
            winRecord.setCreateBy(userName);
            winRecord.setCreateTime(new Date());
            winRecord.setActiveId(activeId);

            winRecordMapper.insert(winRecord);
            return R.ok().setData(winRecord).setMsg("感谢您的参与未中奖");
        }else {
            winRecord.setUserId(userId);
            winRecord.setRuleId(Integer.valueOf(s));
            winRecord.setRecordDesc("已中奖");
            winRecord.setWinFlag(0);
            winRecord.setActiveType(winRecord.getActiveType());
            winRecord.setCreateBy(userName);
            winRecord.setCreateTime(new Date());
            winRecord.setActiveId(activeId);

            Integer ruleId = Integer.valueOf(s);
            ActiveRule activeRule = activeRuleMapper.selectById(ruleId);

            winRecordMapper.insert(winRecord);
            return R.ok().setData(winRecord).setMsg("感谢您的参与：此次中奖的奖品为："+activeRule.getWinProd());
        }


//        //抽奖扣积分
//        Integer payScore = active.getPayScore();
//        R r = iuserService.joinActiveSubScore(userId, payScore);
//        if(r.getCode()!=200){
//            return r;
//        }
    }

    @Override
    public R getJoinRecord(PageInfoVo pageInfoVo) {
        Page<WinRecord> page = new Page<>(pageInfoVo.getPageNum(),pageInfoVo.getPageSize());
//        QueryWrapper<WinRecord> wrapper = new QueryWrapper<>();
//        wrapper.lambda().eq(WinRecord::getActiveId,pageInfoVo.getTypeId());
//        wrapper.lambda().orderByDesc(WinRecord::getCreateTime);
        Page<WinRecord> page1 = winRecordMapper.getJoinRecordList(page, pageInfoVo);
        return R.ok().setData(page1);
    }

    @Override
    public R getActiveById(Integer activeId) {
        Active active = activeMapper.selectById(activeId);
        if(active==null){
            return R.error().setMsg("活动不存在");
        }
        return R.ok().setData(active);
    }

    @Override
    public R joinActiveByScore(Integer activeId) {
        //获取分布式
        String lockKey="activeId-"+activeId;
        RLock lock = redissonClient.getLock(lockKey);

        try {
            //加锁
            lock.lock();
            //积分抽奖
            return joinActive(activeId);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error().setMsg("系统异常");
        }
        finally {
            // 解锁一定要在finally中
            lock.unlock();
        }

    }
}
